﻿#include "RanderTarget.h"

#include "Debuger.h"
#include "Texture2D.h"


FRanderTarget::FRanderTarget()
{
	glGenFramebuffers(1, &FBO);
}

FRanderTarget::~FRanderTarget()
{
	glDeleteFramebuffers(1, &FBO);
}

std::tuple<bool, int32_t> FRanderTarget::BindTextureAsColorAttach(const std::shared_ptr<FTexture2D>& Texture,
	const std::string& TextureName)
{
	const auto Index = GL_COLOR_ATTACHMENT0 + CurrentColorAttachIndex;

	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);
	glFramebufferTexture2D(GL_FRAMEBUFFER, Index, GL_TEXTURE_2D, Texture->GetHandle(), 0);

	BindTextureMap.emplace(TextureName, Texture);

	return std::make_tuple(true, CurrentColorAttachIndex++);
}

bool FRanderTarget::BindRanderBufferAsDepthAttach(const int32_t Width, const int32_t Height) const
{
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);
	GLuint Depthrenderbuffer = 0;
	glGenRenderbuffers(1, &Depthrenderbuffer);
	glBindRenderbuffer(GL_RENDERBUFFER, Depthrenderbuffer);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, Width, Height);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, Depthrenderbuffer);
	return true;
}

bool FRanderTarget::BindTextureAsDepthAttach(const std::shared_ptr<FTexture2D>& Texture, const std::string& TextureName)
{
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, Texture->GetHandle(), 0);
	BindTextureMap.emplace(TextureName, Texture);
	return true;
}

bool FRanderTarget::BindTextureAsDepthAttach(int32_t Width, int32_t Height, const std::string& TextureName)
{
	FTextureBuild Build;

	const auto Texture = Build
		.SetSize(Width, Height)
		.SetFormat(GL_DEPTH_COMPONENT)
		.SetInternalFormat(GL_DEPTH_COMPONENT)
		.SetTextureData(GL_FLOAT, nullptr)
		.Build();

	return BindTextureAsDepthAttach(Texture, TextureName);
}

bool FRanderTarget::BindTextireAsStencilAttach(const std::shared_ptr<FTexture2D>& Texture, const std::string& TextureName)
{
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, Texture->GetHandle(), 0);
	BindTextureMap.emplace(TextureName, Texture);
	return true;
}

bool FRanderTarget::BindTextireAsStencilAttach(int32_t Width, int32_t Height, const std::string& TextureName)
{
	FTextureBuild Build;

	const auto Texture = Build
		.SetSize(Width, Height)
		.SetFormat(GL_STENCIL_INDEX)
		.SetInternalFormat(GL_STENCIL_INDEX)
		.SetTextureData(GL_UNSIGNED_BYTE, nullptr)
		.Build();

	return BindTextireAsStencilAttach(Texture, TextureName);
}

std::shared_ptr<FTexture2D> FRanderTarget::GetTexture(const std::string& TextureName)
{
	if (BindTextureMap.contains(TextureName))
	{
		return BindTextureMap[TextureName];
	}
	return nullptr;
}

void FRanderTarget::Used() const
{
	for (const auto & Texture: BindTextureMap)
	{
		Texture.second->BindTextureUnit(0);
	}

	//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);
	glBindFramebuffer(GL_FRAMEBUFFER, FBO);
	// 高级操作  可以指定画在那个纹理上 搭配 ColorTexture 的 Index
	//glDrawBuffer(FBO);


	const auto State =glCheckFramebufferStatus(GL_FRAMEBUFFER);
	DebugerAssert(State == GL_FRAMEBUFFER_COMPLETE, "%hs", "这个 RTT 不完整");
	
	glClearColor(0.1f, 1.f, 0.1f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
